%{
   #include "ts.h" /* Contains definition of ‘symrec'. */

   enum yytokentype {
      /*IF  = 256, */
      /* ELSE = 257, */
      OPLOG  = 254,      
      BREAK = 255,
      SWITCH = 256, 
      CASE = 257, 
      DEFAULT = 258,
      MEN = 259,
      MEI = 260,
      MAY = 261,
      MAI = 262,
      IGU = 263,
      NOT = 264,
      DIF = 265,
      OPASIG = 266,
      NUMERO = 267,
      POPEN = 268,
      PCLOSE = 269,
      LLOPEN = 270,
      LLCLOSE = 271,
      IDENTIFICADOR = 272
   };

   float yylval;
   
	/* Tabla de símbolos: Lista de nodos 'nodo_ts' */
	token *ts;
%}

obviar         [ \t\n]+
letra_         [A-Za-z_]
digito         [0-9]
identificador  {letra_}({letra_}|{digito})*
numero         [+-]?{digito}+(\.{digito}*)?(E[+-]?{digito}+)? 

%%

{obviar}          {}
{identificador}   { return IDENTIFICADOR; } 
{numero}          { yylval = atof(yytext); return NUMERO; }
"<="              { yylval = MEI; return(OPLOG); }
">"               { yylval = MAY; return(OPLOG); }
">="              { yylval = MAI; return(OPLOG); }
"<"               { yylval = MEN; return(OPLOG); }
"!="              { yylval = DIF; return(OPLOG); }
"!"               { yylval = NOT; return(OPLOG); }
"=="              { yylval = IGU; return(OPLOG); }
"="               { return OPASIG; }
"("				  { return POPEN; }
")"				  { return PCLOSE; }
"{"				  { return LLOPEN; }
"}"				  { return LLCLOSE; }
%%

/* Tabla de símbolos: Lista de nodos tipo token. */
token *ts;

/* 
   Inicialización de la tabla de símbolos:
   1.- Copiado de las palabras reservadas del lenguaje.
*/

void init_table (void) {
   int i;
   token *ptr;
   
/*   ptr = putToken("if", IF, 0.0);*/
/*   ptr = putToken("else", ELSE, 0.0);*/
ptr = putToken("switch", SWITCH, 0.0);
ptr = putToken("case", CASE, 0.0);
ptr = putToken("break", BREAK, 0.0);
ptr = putToken("default", DEFAULT, 0.0);
}

token * putToken (char const *name, int type, double value) {
   token *ptr;
   ptr = (token *) malloc (sizeof (token));
   
   ptr->nombre = (char *) malloc (strlen (name) + 1);
   strcpy (ptr->nombre, name);
   ptr->tipo = type;
   ptr->valor.numero = value;

   ptr->next = (struct token *) ts;
   ts = ptr;
   return ptr;
}

token * getToken (char const *name) {
   token *ptr;
   for (ptr = ts; ptr != (token *) 0; ptr = (token *)ptr->next)
      if (strcmp (ptr->nombre, name) == 0)
         return ptr;
   return 0;
}

void deleteTS() {
   token *ptr;
   
   while(ts != (token *) 0) {
      ptr = ts->next;
      free(ts);
      ts = ptr;
   }
}

void showTS() {
   token *ptr = ts;
   
   printf("\nTokens almacenados en la tabla de símbolos:\n");
   
   while(ptr != (token *) 0) {
      if (ptr->tipo == SWITCH) {
         printf("<SWITCH>");
      } else
      if (ptr->tipo == CASE) {
         printf("<CASE>");
      } else 
      if (ptr->tipo == BREAK) {
         printf("<BREAK>");
      } else
      if (ptr->tipo == DEFAULT) {
         printf("<DEFAULT>");
      } else  
      if (ptr->tipo == IDENTIFICADOR) {
         printf("<IDENTIFICADOR,%s>",ptr->nombre);
      } else {
         printf("Error: Tipo de token desconocido.");
      }
      ptr = ptr->next;
      printf("\n");
   }
   printf("\n");
}

main(int argc, char **argv) {
   int tok;

   if(argc > 1) {
      if(!(yyin = fopen(argv[1], "r"))) {
         printf("ERROR: El archivo de entrada no pudo ser leído.\n");
         exit(0);
      }
   }

   init_table ();

   while(tok=yylex()) {
      if(tok==OPLOG) {
         printf("<OPLOG,%i>",(int)yylval);
      } else
      if(tok==OPASIG) {
         printf("<OPASIG>");
      } else
      if(tok==POPEN) {
         printf("<POPEN>");
      } else
      if(tok==PCLOSE) {
         printf("<PCLOSE>");
      } else
      if(tok==LLOPEN) {
         printf("<LLOPEN>");
      } else
      if(tok==LLCLOSE) {
         printf("<LLCLOSE>");
      } else
      if(tok==NUMERO) {      
         printf("<NUMERO,%.2f>",yylval);
      } else
      if(tok==IDENTIFICADOR) {      
         token *t;
         t = getToken (yytext);
         if (t == 0) {
            t = putToken (yytext, IDENTIFICADOR, 0.0); 
            printf("<IDENTIFICADOR,%s>",yytext);
         } else {
            /*if (t->tipo == IF) {
               printf("<IF>");
            } else*/
            if (t->tipo == SWITCH) {
               printf("<SWITCH>");
            } else
            if (t->tipo == CASE) {
               printf("<CASE>");
            } else
            if (t->tipo == BREAK) {
               printf("<BREAK>");
            } else
            if (t->tipo == DEFAULT) {
               printf("<DEFAULT>");
            } else
            /*if (t->tipo == ELSE) {
               printf("<ELSE>");
            } else*/ {
               printf("<IDENTIFICADOR,%s>",yytext);
            }
         }         
      } else {
         printf("¡ERROR! Cadena no reconocida: %s", yytext);
      }

      printf("\n");
   }
   
   showTS();
   deleteTS();
}
